using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Xeml.Document.EnvironmentalOntology;
using Xeml.Document;
using Xeml.Document.Contracts;

namespace Xid.Controls.ParameterEditCtrls
{
    public partial class VariableTermContextEditCtrl : UserControl
    {
        #region Fields
        private EditMode edtMode;
        private string context;
        private IVariableOntologyTerm paramSpec;
        private string nsAlias;

        private Value _defValue;
        private Value _currentValue;

        private TimeSpan targetTime;
        private VariableTerm _term;
        private Color contextColor;
        #endregion

        #region Properties


        /// <summary>
        /// Gets and sets the current parameter
        /// </summary>
        public VariableTerm Term
        {
            get { return _term; }
            set
            {
                if (_term != null)
                {
                    _term.Values.Cleared -= new EventHandler(OnValuesCleared);
                }
                _term = value;
                if (_term != null)
                {
                    _term.Values.Cleared += new EventHandler(OnValuesCleared);
                }
            }
        }
        #endregion

        public VariableTermContextEditCtrl()
        {

            InitializeComponent();
            buttonSpecHeaderGroupDrop.Visible = false;
            //this.cycleEditorCtrl1.GrowthOrShrink += new EventHandler(cycleEditorCtrl1_GrowthOrShrink);
            //this.radioButtonCycle.CheckedChanged += new EventHandler(OnEditModeChanged);
            //this.radioButtonValue.CheckedChanged += new EventHandler(OnEditModeChanged);

        }


        void OnEditModeChanged(object sender, EventArgs e)
        {


            //if (radioButtonCycle.Checked && !(_currentValue is Cycle) && _currentValue != null) //switch to cycle
            //{
            //    this._defValue = _currentValue as Value;
            //    this._term.Values.Remove(_currentValue);
            //    Cycle c = null;
            //    if (_defCycle != null)
            //    {
            //        c = new Cycle(_defCycle);
            //        c.Time = targetTime;
            //        this._term.Values.Add(c);
            //    }
            //    SetupValue(c, false);

            //}


            //if (_currentValue != null)
            //{

            //    //this._defCycle = _currentValue as Cycle;
            //    this._term.Values.Remove(_currentValue);
            //    Value v = null;
            //    if (_defValue != null)
            //    {
            //        v = new Value(_defValue);

            //        this._term.Values.Add(v);
            //    }
            //    SetupValue(v, false);
            //}

            // SwitchValueEntryMode();


        }




        #region Methods
        /// <summary>
        /// The initialize method for this control.
        /// </summary>
        /// <param name="pspec"></param>
        /// <param name="pcs"></param>
        /// <param name="nsAlias"></param>
        /// <param name="c"></param>
        public void SetupSpec(IVariableOntologyTerm pspec, string context, string nsAlias, Color c)
        {
            this.comboBoxValue.DataBindings.Clear();
            this.numericUpDownValue.DataBindings.Clear();
            this.comboBoxUnit.DataBindings.Clear();


            this.context = context;
            this.paramSpec = pspec;
            this.nsAlias = nsAlias;
            this.contextColor = c;
            FormatMe();
            SetupSpec();
            CalculateDefaultVals();
            //SetupValue();
        }

        /// <summary>
        /// Sets the controls to meet the parameter/context spec.
        /// </summary>
        private void SetupSpec()
        {
            if (!string.IsNullOrEmpty(this.context) && this.paramSpec != null)
            {
                this.kryptonHeaderGroup1.ValuesPrimary.Heading = this.context;
                comboBoxUnit.DataSource = paramSpec.ListUnits(this.context);
                comboBoxUnit.DisplayMember = "Key";
                comboBoxUnit.ValueMember = "Value";
                SetValueEdit();
            }
        }


        private void SwitchValueEntryMode()
        {
            if (this._currentValue == null)
            {
               // cycleEditorCtrl1.Visible = false;
                comboBoxValue.Enabled = false;
                numericUpDownValue.Enabled = false;

                this.comboBoxUnit.Enabled = false;
               // this.radioButtonCycle.Enabled = false;
               // this.radioButtonValue.Enabled = false;
            }
            else if (this._currentValue is Value)
            {
              //  cycleEditorCtrl1.Visible = false;
                comboBoxValue.Enabled = true;
                numericUpDownValue.Enabled = true;

                this.comboBoxUnit.Enabled = this.paramSpec.HasDefaultUnit(this.context);
                //this.radioButtonCycle.Enabled = true;
                //this.radioButtonValue.Enabled = true;
            }
            //else if (this._currentValue is Cycle)
            //{
            //    cycleEditorCtrl1.Visible = true;
            //    comboBoxValue.Enabled = false;
            //    numericUpDownValue.Enabled = false;

            //    this.comboBoxUnit.Enabled = this.paramSpec.HasDefaultUnit(this.context);
            //    this.radioButtonCycle.Enabled = true;
            //    this.radioButtonValue.Enabled = true;
            //}
            // OnResize(new EventArgs());  //Because of the kryptongroupbox-autoresize bug
        }
        /// <summary>
        /// Sets the current value for editing.
        /// </summary>
        /// <param name="v"></param>
        public void SetupValue(Value v, bool changeCheckedState)
        {

            if (this._currentValue != null)
            {

                this._currentValue.PropertyChanged -= new PropertyChangedEventHandler(_currentValue_PropertyChanged);
            }
            this._currentValue = v;


            SetSecondaryHeader();
            SwitchValueEntryMode();
            //if (this.val != null)
            //    this.targetTime = v.Time;
            if (this._currentValue == null)
            {
                this.buttonSpecHeaderGroupDrop.Visible = false;
                this.buttonSpecHeaderGroupPopulate.Visible = true;
                //if (changeCheckedState)
                //    radioButtonValue.Checked = true;
                //this.kryptonHeaderGroup1.ValuesSecondary.Heading = this.targetTime.ToString();
                //this.kryptonHeaderGroup1.ValuesSecondary.Description = "null";

                //this.comboBoxUnit.Enabled = false;
                //this.comboBoxValue.Enabled = false;
                //this.numericUpDownValue.Enabled = false;
                //this.radioButtonCycle.Enabled = false;
                //this.radioButtonValue.Enabled = false;
            }
            else
            {
                this._currentValue.PropertyChanged += new PropertyChangedEventHandler(_currentValue_PropertyChanged);
                this.buttonSpecHeaderGroupDrop.Visible = true;
                this.buttonSpecHeaderGroupPopulate.Visible = false;

                this.comboBoxValue.DataBindings.Clear();
                this.numericUpDownValue.DataBindings.Clear();
                this.comboBoxUnit.DataBindings.Clear();
                this.comboBoxUnit.DataBindings.Add("SelectedValue", _currentValue, "Unit", true, DataSourceUpdateMode.OnPropertyChanged);
                if (this._currentValue is Value)
                {
                    //this.radioButtonCycle.CheckedChanged -= new EventHandler(OnEditModeChanged);
                    //this.radioButtonValue.CheckedChanged -= new EventHandler(OnEditModeChanged);
                    //if (changeCheckedState)
                    //    radioButtonValue.Checked = true;

                    //this.radioButtonCycle.CheckedChanged += new EventHandler(OnEditModeChanged);
                    //this.radioButtonValue.CheckedChanged += new EventHandler(OnEditModeChanged);



                    switch (this.edtMode)
                    {
                        case EditMode.ComboValue:
                            {
                                this.comboBoxValue.DataBindings.Add("Text", _currentValue, "Val", true, DataSourceUpdateMode.OnPropertyChanged);
                                //this.comboBoxValue.Text = ((Value)this._currentValue).Val;
                                break;
                            }
                        case EditMode.ComboListValue:
                            {
                                this.comboBoxValue.DataBindings.Add("SelectedValue", _currentValue, "Val", true, DataSourceUpdateMode.OnPropertyChanged);
                                // this.comboBoxValue.SelectedValue = ((Value)this._currentValue).Val;
                                break;
                            }
                        case EditMode.NumericValue:
                            {
                                this.numericUpDownValue.DataBindings.Add("Value", _currentValue, "DoubleValue", true, DataSourceUpdateMode.OnPropertyChanged);
                                //this.numericUpDownValue.Value = (decimal)((Value)this._currentValue).DoubleValue;
                                break;
                            }
                        case EditMode.BooleanValue:
                            {
                                //  this.checkBox.DataBindings.Add("Checked", _currentValue, "BooleanValue", true, DataSourceUpdateMode.OnPropertyChanged);
                                this.comboBoxValue.DataBindings.Add("SelectedValue", _currentValue, "BooleanValue", true, DataSourceUpdateMode.OnPropertyChanged);

                                //this.numericUpDownValue.Value = (decimal)((Value)this._currentValue).DoubleValue;
                                break;
                            }

                        default:
                            break;
                    }
                }


                //this.comboBoxUnit.Enabled = true;
                //this.comboBoxValue.Enabled = true;
                //this.numericUpDownValue.Enabled = true;
                //this.radioButtonCycle.Enabled = true && this.paramSpec.AllowCycling;
                //this.radioButtonValue.Enabled = true;


            }


            FormatMe();
        }

        void _currentValue_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            SetSecondaryHeader();
            if (e.PropertyName == "Time" && ValueTimeChanged != null)
            {

            }
        }



        private void SetSecondaryHeader()
        {
            if (_currentValue != null)
            {
                //   this.kryptonHeaderGroup1.ValuesSecondary.Heading = this._currentValue.Time.ToString();// +" " + 
                this.kryptonHeaderGroup1.ValuesSecondary.Heading = this._currentValue.Val + " " + _currentValue.Unit;
            }
            else
            {
                // this.kryptonHeaderGroup1.ValuesSecondary.Heading = this.targetTime.ToString();// +" " + 
                this.kryptonHeaderGroup1.ValuesSecondary.Description = "---";
            }
        }



        /// <summary>
        /// Sets the edit mode in respect to the parameter/context specification
        /// </summary>
        private void SetValueEdit()
        {

            if (paramSpec.GetEnums(this.context).Count > 0)
            {
                this.edtMode = EditMode.ComboListValue;
                comboBoxValue.Visible = true;
                numericUpDownValue.Visible = false;
                comboBoxValue.DropDownStyle = ComboBoxStyle.DropDownList;
                comboBoxValue.DataSource = paramSpec.GetEnums(this.context);
                comboBoxValue.DisplayMember = "Key";
                comboBoxValue.ValueMember = "Value";
                return;
            }
            if (paramSpec.GetDataType(this.context) == VariableDataTypes.Number)
            {
                this.edtMode = EditMode.NumericValue;
                comboBoxValue.Visible = false;
                numericUpDownValue.Visible = true;
                numericUpDownValue.DecimalPlaces = 2;
                decimal? mi = paramSpec.GetMin(this.context);
                decimal? mx = paramSpec.GetMax(this.context);
                if (mi != null)
                    numericUpDownValue.Minimum = (decimal)mi;
                if (mx != null)
                    numericUpDownValue.Maximum = (decimal)mx;
            }
            if (paramSpec.GetDataType(this.context) == VariableDataTypes.Bool)
            {
                this.edtMode = EditMode.BooleanValue;
                //BindingList<bool> bl = new BindingList<bool>();

                List<KeyValuePair<bool, bool>> bl = new List<KeyValuePair<bool, bool>>();

                bl.Add(new KeyValuePair<bool, bool>(true, true));
                bl.Add(new KeyValuePair<bool, bool>(false, false));

                comboBoxValue.Visible = true;
                numericUpDownValue.Visible = false;
                comboBoxValue.DropDownStyle = ComboBoxStyle.DropDownList;
                comboBoxValue.DataSource = bl;
                comboBoxValue.DisplayMember = "Key";
                comboBoxValue.ValueMember = "Value";



            }

            if (paramSpec.GetDataType(this.context) == VariableDataTypes.Text)
            {
                this.edtMode = EditMode.ComboValue;
                //BindingList<bool> bl = new BindingList<bool>();
                //bl.Add(true);
                //bl.Add(false);
                comboBoxValue.Visible = true;
                numericUpDownValue.Visible = false;
                comboBoxValue.DropDownStyle = ComboBoxStyle.DropDown;
                //comboBoxValue.DataSource = bl;

            }
        }

        /// <summary>
        /// Makes color settings and assigns strings.
        /// </summary>
        private void FormatMe()
        {
            this.kryptonHeaderGroup1.ValuesPrimary.Heading = this.context;

            if (this._currentValue != null)
            {
                this.kryptonHeaderGroup1.StateCommon.HeaderPrimary.Back.Color2 = contextColor;
                this.kryptonHeaderGroup1.StateCommon.HeaderSecondary.Back.Color2 = contextColor;
                this.kryptonHeaderGroup1.StateCommon.HeaderPrimary.Content.ShortText.Color1 = Color.White;
                this.kryptonHeaderGroup1.StateCommon.HeaderSecondary.Content.ShortText.Color1 = Color.White;
                this.kryptonHeaderGroup1.StateCommon.HeaderSecondary.Content.LongText.Color1 = Color.White;
            }
            else
            {
                this.kryptonHeaderGroup1.StateCommon.HeaderPrimary.Back.Color2 = Color.Gray;
                this.kryptonHeaderGroup1.StateCommon.HeaderSecondary.Back.Color2 = Color.Gray;
                this.kryptonHeaderGroup1.StateCommon.HeaderPrimary.Content.ShortText.Color1 = Color.Silver;
                this.kryptonHeaderGroup1.StateCommon.HeaderSecondary.Content.ShortText.Color1 = Color.Silver;
                this.kryptonHeaderGroup1.StateCommon.HeaderSecondary.Content.LongText.Color1 = Color.Silver;
            }
        }

        /// <summary>
        /// Populates a new parameter according to the current spec.
        /// </summary>
        private void PopulateParameter()
        {
            this._term = (VariableTerm)paramSpec.EmitDefaultObject(false);
            this._term.Values.Clear();
        }

        /// <summary>
        /// Populates a value according to the current spec.
        /// </summary>
        private void Populate()
        {
            if (!string.IsNullOrEmpty(this.context))
            {
                bool raiseEvent = false;
                if (this._term == null)
                {
                    PopulateParameter();
                    raiseEvent = true;
                }
                if (_defValue != null)
                {
                    Value v = new Value(_defValue);
                    // v.Time = this.targetTime;
                    this._term.Values.Add(v);
                    SetupValue(v, true);
                }

                if (raiseEvent && this.ParameterPopulated != null)
                    ParameterPopulated(this, new EventArgs());
            }
        }


        private void CalculateDefaultVals()
        {
            if (!string.IsNullOrEmpty(this.context))
            {


                _defValue = (Value)paramSpec.DefaultValue(this.context);
                // _defValue.Context = this.paramContextSpec.Name;





                if (paramSpec.HasDefaultUnit(this.context))
                {

                    _defValue.Unit = paramSpec.DefaultUnitSymbol(this.context);
                }
            }
        }

        /// <summary>
        /// Drops the curretn value.
        /// </summary>
        public void DropValue()
        {
            if (this._term != null)
            {
                this._term.Values.Remove(this._currentValue);
                if (this._term.Values.Count == 0)
                {
                    if (ParameterDePopulated != null)
                        ParameterDePopulated(this, new EventArgs());
                }
            }
            SetupValue(null, true);
        }
        #endregion

        #region Eventhandler
        /// <summary>
        /// Eventhandler for the populate command.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnPopulate_Click(object sender, EventArgs e)
        {
            Populate();
        }

        /// <summary>
        /// Eventhandler for the drop command.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnDrop_Click(object sender, EventArgs e)
        {
            DropValue();
        }

        /// <summary>
        /// Eventhandler for the values cleared event.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnValuesCleared(object sender, EventArgs e)
        {
            this.targetTime = TimeSpan.Zero;
            SetupValue(null, true);
        }
        #endregion

        #region Events

        public event EventHandler ParameterPopulated;
        public event EventHandler ParameterDePopulated;
        public event EventHandler ValueTimeChanged;
        #endregion




    }


}
